package pers.cz.ssh;

import ch.ethz.ssh2.Connection;
import ch.ethz.ssh2.Session;
import cn.hutool.extra.ssh.JschUtil;
import com.jcraft.jsch.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

/**
 * ssh工具类
 * @program: PostGirl-panent
 * @description: SshUtil
 * @author: Cheng Zhi
 * @create: 2021-11-29 10:42
 **/
public class SshUtil {

    Logger logger = LoggerFactory.getLogger(SshUtil.class);

    private Connection connect;

    private com.jcraft.jsch.Session session;
    private ChannelExec exec;

    /**
     * 登录主机,ssh2对OpenSSH_8.2p1, OpenSSL 1.1.1q  5 Jul 2022版本支持不友善。
     * @param host
     * @param port
     * @param user
     * @param password
     * @return
     */
    public boolean loginWithSsh2(String host, Integer port, String user, String password) {
        connect = new Connection(host,port);
        try {
            connect.connect();
            return connect.authenticateWithPassword(user, password);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            return false;
        }
    }

    /**
     * 使用Jsch做为ssh
     * @param host
     * @param port
     * @param user
     * @param password
     * @return
     */
    public boolean login(String host, Integer port, String user, String password) {
        try {
            JSch jsch = new JSch();
            logger.info("ssh connect by host:{} username:{}",host,user);

            session = jsch.getSession(user, host, port);
            logger.info("Session is build");
            if (password != null) {
                session.setPassword(password);
            }
            Properties config = new Properties();
            config.put("StrictHostKeyChecking", "no");

            session.setConfig(config);
            session.connect();
            logger.info("Session is connected");

            return true;
        } catch (JSchException e) {
            logger.error("Cannot connect to specified ssh server : {}:{} \n Exception message is: {}", new Object[]{host, port, e.getMessage()});
        }
        return false;
    }

    /**
     * 获取返回信息
     * @param in
     * @return
     */
    private StringBuilder processStdout(InputStream in) {
        byte[] buf = new byte[1024];
        StringBuilder builder = new StringBuilder();
        try {
            int length;
            while ((length = in.read(buf)) != -1) {
                builder.append(new String(buf, 0, length));
            }
        } catch (IOException e) {
            logger.error(e.getMessage(), e);
        }
        return builder;
    }

    /**
     * 执行命令
     * @param shell
     * @param isLogin
     * @return
     * @throws IOException
     */
    public StringBuilder exec(String shell, Boolean isLogin) throws IOException {
        StringBuilder result = new StringBuilder();
        // 认证登录信息
        if (isLogin) {
            result = exec(shell);
        }

        logger.info("命令执行结果：" + result.toString());
        return result;
    }

    /**
     * 登录之后执行命令，不会关闭连接，执行完命令后不需要重复登录
     * @param shell
     * @return
     * @throws IOException
     */
    public StringBuilder exec(String shell) throws IOException {
        InputStream inputStream = null;
        InputStream errorInputStream = null;
        StringBuilder result = new StringBuilder();
        try {
            exec = (ChannelExec) session.openChannel("exec");
            exec.setCommand(shell);
            exec.setErrStream(System.err);
            exec.connect();
            logger.info("开始执行命令");
            inputStream = exec.getInputStream();
            errorInputStream = exec.getErrStream();
            result = this.processStdout(inputStream);
            if (null != errorInputStream) {
                result.append(this.processStdout(errorInputStream));
            }

        } catch (JSchException e) {
            logger.error(e.getMessage(), e);
        } finally {
            if (null != inputStream) {
                inputStream.close();
            }
            if (null != errorInputStream) {
                errorInputStream.close();
            }
        }
        return result;
    }

    /**
     * 关闭连接 server
     */
    public void logout(){
        if (session != null) {
            if (session.isConnected()) {
                session.disconnect();
                logger.info("sftp is closed already");
            }
        }
        if (session != null) {
            if (session.isConnected()) {
                session.disconnect();
                logger.info("sshSession is closed already");
            }
        }
    }
    /**
     * 执行命令
     * @param shell
     * @param isLogin
     * @return
     * @throws IOException
     */
    public StringBuilder execWithSsh2(String shell, Boolean isLogin) throws IOException {
        InputStream inputStream = null;
        StringBuilder result = new StringBuilder();
        try {
            // 认证登录信息
            if (isLogin) {
                // 登陆成功则打开一个会话
                Session session = connect.openSession();
                if (shell != null && !shell.isEmpty()) {
                    session.execCommand(shell);
                }

                inputStream = session.getStdout();
                result = this.processStdout(inputStream);
                connect.close();
            }
        } finally {
            if (null != inputStream) {
                inputStream.close();
            }
        }
        return result;
    }

    /**
     * 登录之后执行命令，不会关闭连接，执行完命令后不需要重复登录
     * @param shell
     * @return
     * @throws IOException
     */
    public StringBuilder execWithSsh2(String shell) throws IOException {
        InputStream inputStream = null;
        StringBuilder result = new StringBuilder();
        try {
            Session session = connect.openSession();
            if (shell != null && !shell.isEmpty()) {
                session.execCommand(shell);
            }

            inputStream = session.getStdout();
            result = this.processStdout(inputStream);
        } finally {
            if (null != inputStream) {
                inputStream.close();
            }
        }
        return result;
    }

    public String getRealWorkPath() throws IOException {
        this.exec("cd ~");
        StringBuilder userWorkPath = this.exec("pwd");
        String realPath = userWorkPath.toString();
        return realPath;
    }
    public String getRealWorkPath(String workpath) throws IOException {
        String userWorkPath = this.getRealWorkPath();
        String realPath = userWorkPath + workpath;

        return realPath;
    }

    public static void main(String[] args) {
        String shell = "";
        if (shell.isEmpty()) {
            System.out.println("为空");
        } else {
            System.out.println("不为空");
        }
        Integer permissions = 1;
        System.out.println(permissions & '耀');
        System.out.println((permissions & '耀') == 32768);
    }
}
